import tempfile

import pandas as pd
from django.core.mail import send_mail
from django.core.paginator import Paginator
from django.http import HttpResponse

# Create your views here.
from django.utils.dateparse import parse_datetime
from rest_framework import status
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.permissions import BasePermission
from rest_framework.response import Response
from rest_framework.views import APIView
from CourseAdjustmentManagement.models import TeacherChangeClassRecord
from CourseAdjustmentManagement.serializers import TeacherChangeClassRecordSerializer
from CourseAdjustmentManagement.views.views import model_info_dict
from HopeIESystem.settings import DEFAULT_FROM_EMAIL
from UserManager.models import User


class IsReviewer(BasePermission):

    def has_permission(self, request, view):
        # 假设您有一个名为 'reviewer' 的用户组

        return request.user.groups.filter(name='reviewer').exists()


class IsTDAdmin(BasePermission):
    def has_permission(self, request, view):
        # 假设您有一个名为 'TDAdmin' 的用户组

        return request.user.groups.filter(name='TDAdmin').exists()


class IsTDAdminOrIsReviewer(BasePermission):
    def has_permission(self, request, view):
        # 检查用户是否是管理员或审核者
        return request.user.groups.filter(name='TDAdmin').exists() or request.user.groups.filter(
            name='reviewer').exists()


# 创建
class CreateView(APIView):
    # 定义一个Report字段为空对象
    permission_classes = [IsTDAdminOrIsReviewer]
    model = None
    Serializer = None

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        try:
            # 获取字段从而知道操作哪个模型类与序列化类

            self.model = TeacherChangeClassRecord
            self.Serializer = TeacherChangeClassRecordSerializer
            return self.get_reports(request)
        except Exception as e:
            return Response({'error': 'Invalid data:' + str(e)}, status=status.HTTP_400_BAD_REQUEST)

    def get_reports(self, request):
        # 将request.data中的数据序列化后添加到model中。
        serializer = self.Serializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({'success': '数据添加成功'}, status=201)
        else:
            return Response({'error': '无效数据: ' + str(serializer.errors)}, status=400)


# 删除条目
class DeleteView(APIView):
    permission_classes = [IsTDAdminOrIsReviewer]
    model = None
    Serializer = None

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        try:
            # 获取字段从而知道操作哪个模型类与序列化类
            self.model = TeacherChangeClassRecord
            self.Serializer = TeacherChangeClassRecordSerializer
            report = self.model.objects.get(id=request.data['id'])

            return self.get_reports(report)
        except Exception as e:
            return Response({'error': '无效数据:' + str(e)}, status=400)

    def get_reports(self, report):
        # 获取id，根据id删除该条目
        report.delete()
        return Response({'success': '数据已经删除'}, status=200)


# 修改条目
class UpdateView(APIView):
    permission_classes = [IsTDAdminOrIsReviewer]
    model = None
    Serializer = None

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        try:
            self.model = TeacherChangeClassRecord
            self.Serializer = TeacherChangeClassRecordSerializer
            report = self.model.objects.get(id=request.data['id'])

            return self.get_reports(request, report)
        except Exception as e:
            return Response({'error': '无效数据: ' + str(e)}, status=400)

    def get_reports(self, request, report):
        # 获取id，根据id修改该条目,用序列化

        serializer = self.Serializer(report, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({'success': '管理员修改成功'}, status=200)
        else:
            return Response({'error': '提交了无效数据:' + str(serializer.errors)}, status=400)


# 获取所有条目
class GetView(APIView):
    permission_classes = [IsTDAdminOrIsReviewer]
    model = None
    Serializer = None

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        # try:
        try:
            self.model = TeacherChangeClassRecord
            self.Serializer = TeacherChangeClassRecordSerializer
            return self.get_reports(request)
        except Exception as e:
            return Response({'error': 'Invalid data:' + str(e)}, status=400)

    # except Exception as e:
    #     return Response({'error': 'Invalid data:' + str(e)}, status=400)

    def get_reports(self, request):
        # 根据id返回TrainingReport
        reports = self.filter_reports_by_time(request)
        total_datas = len(reports)

        if request.data['page']:
            # 创建分页器实例，每页显示10条记录
            paginator = Paginator(reports, 10)
            # 获取当前页面
            page_number = request.data['page']
            reports = paginator.get_page(page_number)

        serializer = self.Serializer(reports, many=True, context={'request': request})
        return Response({'total_datas': total_datas, 'datas': serializer.data}, status=200)

    def filter_reports_by_time(self, request):
        start_time = request.data.get('start_time')
        end_time = request.data.get('end_time')
        if not start_time or not end_time:
            return Response({"error": "请提供 start_time 和 end_time 参数"}, status=status.HTTP_400_BAD_REQUEST)
            # 将字符串时间转换为 Python datetime 对象
        start_time = parse_datetime(start_time)
        end_time = parse_datetime(end_time)

        # 应用时间范围过滤
        reports = self.model.objects.filter(created_at__range=(start_time, end_time))

        return reports


# 增：上传附件
class AddFileView(APIView):
    parser_classes = [MultiPartParser, FormParser]  # 添加支持multipart/form-data的解析器
    model = None
    Serializer = None

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        try:
            self.model = TeacherChangeClassRecord
            self.Serializer = TeacherChangeClassRecordSerializer
            report = self.model.objects.get(id=request.data['id'])
            if request.user.username != report.teacher_id:
                return Response({'error': '你不是这个数据的责任人，不可操作'}, status=status.HTTP_403_FORBIDDEN)
            else:
                return self.get_reports(request, report)

        except Exception as e:
            return Response({'error': '无效数据 : ' + str(e)}, status=400)

    def get_reports(self, request, report):
        # 上传附件信息
        # 获取上传的文件对象
        try:
            uploaded_file = request.FILES.get('file')  # 尝试从请求中获取文件

            if uploaded_file:
                # 如果有文件被上传，将其保存到报告的attachment字段
                report.attachment = uploaded_file
                report.save()
                return Response({"message": "上传文件成功."}, status=status.HTTP_200_OK)
            else:
                return Response({"message": "没有文件被上传."}, status=status.HTTP_400_BAD_REQUEST)

        except Exception as e:
            return Response({"message": "上传文件失败: " + str(e)}, status=status.HTTP_400_BAD_REQUEST)


# 审批
class ApprovalView(APIView):
    # 仅reviewer组的用户可以访问
    permission_classes = [IsTDAdminOrIsReviewer]
    model = None
    Serializer = None

    def post(self, request):
        try:
            self.model = TeacherChangeClassRecord
            self.Serializer = TeacherChangeClassRecordSerializer
            report = self.model.objects.get(id=request.data['id'])
            return self.get_reports(request, report)
        except Exception as e:
            return Response({'error': '无效数据:' + str(e)}, status=400)

    def get_reports(self, request, report):
        # 获取id，根据id修改该条目,不用序列化
        try:
            # 获取id，根据id修改该条目,不用序列化
            report.revstatus = request.data['revstatus']
            report.save()
            message = "你的调课申请已审批，请前往官网查看审批结果：http://xgreport.swjtuhc.top:1080/"
            if self.send_email(message, report):
                pass
            else:
                return Response({"message": "审批成功 但邮件发送失败，请注意通知该老师"}, status=status.HTTP_200_OK)
            return Response({"message": "审批成功"}, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({"error": "审批失败：" + str(e)}, status=status.HTTP_400_BAD_REQUEST)

    def send_email(self, message, report):

        try:
            username = report.teacher_id
            # 从User模型中获取这个对象
            emails = [User.objects.get(username=username).email]
            # 发送邮件
            send_mail(
                '希望信工系--调课通知',
                message,
                DEFAULT_FROM_EMAIL,
                emails,
                fail_silently=False,
            )
            return True
        except:
            return False


# 下载excel
class DownloadExcelView(APIView):
    permission_classes = [IsTDAdminOrIsReviewer]
    model = None
    Serializer = None

    def post(self, request):
        # 判断是否request.user.name ==request.data.name
        # 如果是，则继续处理POST请求
        # 返回所有TrainingReport满足 TrainingReport.objects.author[0]==request.user.name的条目
        # 如果不是，则返回错误信息
        # try:
        try:
            excel_dir = {}
            excel_data = {}
            self.model = TeacherChangeClassRecord
            self.Serializer = TeacherChangeClassRecordSerializer
            reports = self.get_reports(request)
            df = pd.DataFrame(reports.data)
            excel_dir = {col: df[col].tolist() for col in df.columns}
            for key, value in excel_dir.items():
                excel_data[model_info_dict['TeacherChangeClassRecord'][key]["verbose_name"]] = value

            # 将excel_dir 转为excel 并返回下载
            return self.generate_excel_response(excel_data)
        except Exception as e:
            return Response({'error': 'Invalid data:' + str(e)}, status=400)

    # except Exception as e:
    #     return Response({'error': 'Invalid data:' + str(e)}, status=400)

    def get_reports(self, request):
        # 根据id返回TrainingReport
        reports = self.filter_reports_by_time(request)
        if not request.data['interval']:
            reports = reports.all()
        else:
            start = request.data['interval'][0]
            end = min(request.data['interval'][1], len(reports))
            reports = reports[start:end]

        serializer = self.Serializer(reports, many=True, context={'request': request})
        return Response(serializer.data, status=200)

    def filter_reports_by_time(self, request):
        start_time = request.data.get('start_time')
        end_time = request.data.get('end_time')
        if not start_time or not end_time:
            return Response({"error": "请提供 start_time 和 end_time 参数"}, status=status.HTTP_400_BAD_REQUEST)
            # 将字符串时间转换为 Python datetime 对象
        start_time = parse_datetime(start_time)
        end_time = parse_datetime(end_time)

        # 应用时间范围过滤
        reports = self.model.objects.filter(created_at__range=(start_time, end_time))

        return reports

    def generate_excel_response(self, excel_data):
        # 使用pandas创建DataFrame
        df = pd.DataFrame(excel_data)

        # 创建一个Excel写入器
        with tempfile.NamedTemporaryFile(delete=False, suffix='.xlsx') as tmp:
            # 创建一个Excel写入器，写入临时文件
            with pd.ExcelWriter(tmp.name, engine='xlsxwriter') as writer:
                # 将DataFrame写入Excel文件
                df.to_excel(writer, index=False)

            # 创建一个HTTP响应对象，包含Excel文件
            with open(tmp.name, 'rb') as excel_file:
                response = HttpResponse(excel_file.read(),
                                        content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
                response['Content-Disposition'] = 'attachment; filename="temp.xlsx"'
                return response
